home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / exemod.zip / EXEMOD.C < prev    next >
Text File  |  1990-03-27  |  5KB  |  166 lines

  1. /*
  2. EXEMOD.C - Modify global variables in EXE or COM file
  3.  
  4. Kevin Dean
  5. 16 Kellythorne Drive
  6. Don Mills, Ontario
  7. Canada  M3A 2L4
  8.  
  9. March 27, 1990
  10.  
  11. Modifies global variables in initialized data segment of EXE or COM files.
  12. Cannot modify global variables that are declared but not initialized as these
  13. lie in the BSS segment of the program and are not in fact in the EXE image file
  14. itself.
  15.  
  16. Copyright (c) 1990 by Kevin Dean
  17.  
  18. For Turbo C versions 2.0 and above.  This code is public domain.
  19. */
  20.  
  21.  
  22. #include <dir.h>
  23. #include <dos.h>
  24. #include <errno.h>
  25. #include <fcntl.h>
  26. #include <io.h>
  27. #include <stdarg.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30.  
  31. #include <exemod.h>
  32.  
  33.  
  34. /***/
  35. /*
  36. Name        exemodify
  37.  
  38. Function    Modifies static data in EXE or COM files.
  39.  
  40. Syntax        int exemodify(char *progname, int keepdt, [void *data1,
  41.                unsigned n1, [void *data2, unsigned n2, [ ... ]]]
  42.                NULL);
  43.  
  44. Prototype in    exemod.h
  45.  
  46. Remarks        exemodify modifies global variables in the initialized data
  47.         segment of the current EXE or COM file.  In DOS versions 3.0
  48.         and up, exemodify takes the program name from _argv[0].  In DOS
  49.         versions below 3.0, exemodify searches the DOS path for the
  50.         program passed in progname.
  51.  
  52.         If keepdt is true, then the original file date/time stamp is
  53.         preserved.
  54.  
  55.         exemodify cannot modify global variables that are declared but
  56.         not initialized as these lie in the BSS segment of the program
  57.         and are not in fact in the EXE or COM image file itself.
  58.  
  59.         WARNING: Huge model programs treat uninitialized data the same
  60.         as initialized data with values of 0 in that the uninitialized
  61.         data is also written to the EXE file.  Because of the model,
  62.         the Turbo C startup code does not initialize this data to 0.
  63.         Since the compiler itself does not differentiate between
  64.         initialized and uninitialized data in the huge model, neither
  65.         can this module, and so any changes written to what was
  66.         intended to be the uninitialized data segment in the huge model
  67.         could have unpredictable results.
  68.  
  69. Return value    exemodify returns the number of data items successfully
  70.         modified (which may not be the same as the number of items
  71.         passed) or -1 in case of error (such as file not found or
  72.         invalid EXE file format).
  73.  
  74.         In the event of an error, the global variable errno is set to
  75.         one of the following:
  76.  
  77.             ENOENT        No such file or directory
  78.             EMFILE        Too many open files
  79.             EACCES        Permission denied
  80.             EINVACC        Invalid access code
  81.             EINVFMT        Invalid format
  82.  
  83. Portability    exemodify is unique to DOS.
  84. */
  85. int exemodify(const char *progname, int keepdt, ...)
  86. {
  87. char *pathptr;            /* Pointer to program path */
  88. char _progname[MAXPATH];    /* Program name */
  89. int retcode;            /* Function return code */
  90. char ext[MAXEXT];        /* Program extension */
  91. int progfile;            /* Program file handle */
  92. int iscomfile;            /* True if program is a COM file */
  93. struct exeheader exe;        /* EXE file header */
  94. long filelen;            /* Program file length */
  95. struct ftime dtstamp;        /* Program date/time stamp */
  96. va_list datalist;        /* List of data items to be written to file */
  97. char *data;            /* Pointer to current data item */
  98. unsigned n;            /* Size of current data item */
  99. long seeklen;            /* Seek length into program file */
  100.  
  101. if (_osmajor < 3)
  102.   /* Search DOS PATH for program */
  103.   if ((pathptr = searchpath(progname)) != NULL)
  104.     strcpy(_progname, pathptr);
  105.   else
  106.     _progname[0] = 0;
  107. else
  108.   /* Program name is 0th parameter in DOS versions 3.0 and up */
  109.   strcpy(_progname, _argv[0]);
  110.  
  111. /* Assume error */
  112. retcode = -1;
  113.  
  114. if (_progname[0])
  115.   {
  116.   if ((progfile = open(_progname, O_RDWR | O_BINARY)) != -1)
  117.     {
  118.     iscomfile = fnsplit(_progname, NULL, NULL, NULL, ext) & EXTENSION && !strnicmp(ext, ".COM", 4);
  119.  
  120.     if (!iscomfile && (read(progfile, &exe, EXEH_SIZE) != EXEH_SIZE || exe.id != EXE_ID))
  121.       /* File is not a COM file and does not have a valid EXE file header */
  122.       errno = EINVFMT;
  123.     else
  124.       {
  125.       /* Cannot write beyond end of file */
  126.       filelen = filelength(progfile);
  127.  
  128.       if (keepdt)
  129.     /* Save date/time stamp */
  130.     getftime(progfile, &dtstamp);
  131.  
  132.       retcode = 0;
  133.       va_start(datalist, keep_attribs);
  134.  
  135.       while ((data = va_arg(datalist, char *)) != NULL)
  136.     {
  137.     if (iscomfile)
  138.       /* Seek length is data offset - PSP size */
  139.       seeklen = FP_OFF(data) - 256;
  140.     else
  141.       /* Seek length is (data segment - (PSP + PSP size) + EXE size) * 16 + data offset */
  142.       seeklen = ((unsigned long)(FP_SEG(data) - (_psp + 16) + exe.size) << 4) + (unsigned long)FP_OFF(data);
  143.  
  144.     n = va_arg(datalist, unsigned);
  145.  
  146.     if (seeklen + n <= filelen && lseek(progfile, seeklen, SEEK_SET) != -1L && write(progfile, data, n) == n)
  147.       /* Seek and write was successful */
  148.       retcode++;
  149.     }
  150.  
  151.       va_end(datalist);
  152.  
  153.       if (keepdt)
  154.     /* Restore date/time stamp */
  155.     setftime(progfile, &dtstamp);
  156.       }
  157.  
  158.     close(progfile);
  159.     }
  160.   }
  161. else
  162.   /* File not found */
  163.   errno = ENOENT;
  164.  
  165. return (retcode);
  166. }